﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
//using System.Web.UI.WebControls.WebParts;

using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Administration;

using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.SharePoint.Common.ServiceLocation;
using Microsoft.Practices.SharePoint.Common.Logging;

namespace EFSPWebParts
{
    class Program
    {
        #region common functions

        public static void MyTraceToDeveloper(string strMessage)
        {
            Console.WriteLine(strMessage);
        }

        public static void MyTraceToDeveloper(ILogger _logger, string strMessage)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.TraceToDeveloper(string.Format("EFSPWebParts.test - {0}", strMessage), TraceSeverity.Monitorable);
            });
        }

        public static void MyLogToOperations(ILogger _logger, string strMessage)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.LogToOperations(string.Format("EFSPWebParts.test - {0}", strMessage), 0, EventSeverity.ErrorCritical);
            });
        }

        public static void MyLogToOperations(ILogger _logger, Exception ex)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                _logger.LogToOperations(ex, @"EFSPWebParts.test");
            });
        }
        #endregion

        #region member variables

        public const string ColumnNameFileName = @"FileName";
        public const string ColumnNameFileUrl = @"FileUrl";
        public const string ColumnNameFileSize = @"FileSize";
        public const string ColumnNameModified = @"Modified";
        public const string ColumnNameModifiedBy = @"ModifiedBy";
        public const string ColumnNameModifiedByUrl = @"ModifiedByUrl";
        public const long lMBsize = 1024 * 1024;

        #endregion

        public static DataTable ConvertDataTable(SPSite objSPSite, DataTable objDataTableSource)
        {
            ILogger _logger = SharePointServiceLocator.GetCurrent().GetInstance<ILogger>();

            MyTraceToDeveloper(_logger, string.Format("dtSource.Rows.Count={0}", objDataTableSource.Rows.Count));

            DataTable dtDestination = new DataTable();
            DataColumn objDataColumn = null;
            DataRow objDataRow = null;

            string strModifiedId = SPBuiltInFieldId.Modified.ToString("B");
            string strFileUrlId = SPBuiltInFieldId.URL.ToString("B");
            Guid objGuidWebId = Guid.Empty;
            Guid objGuidListId = Guid.Empty;
            int ItemId = int.MinValue;

            SPServiceContext objSPServiceContext = null;
            UserProfileManager objUserProfileManager = null;

            try
            {
                foreach (DataColumn objDataColumnTmp in objDataTableSource.Columns)
                {
                    MyTraceToDeveloper(_logger, string.Format("ColumnName={0}, DataType={1}", objDataColumnTmp.ColumnName, objDataColumnTmp.DataType));
                }

                //return null;

                objDataColumn = new DataColumn(ColumnNameFileName, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameFileUrl, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameFileSize, System.Type.GetType("System.Decimal"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameModified, System.Type.GetType("System.DateTime"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameModifiedBy, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);
                objDataColumn = new DataColumn(ColumnNameModifiedByUrl, System.Type.GetType("System.String"));
                dtDestination.Columns.Add(objDataColumn);

                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    objSPServiceContext = SPServiceContext.GetContext(objSPSite);
                    objUserProfileManager = new UserProfileManager(objSPServiceContext);

                    foreach (DataRow objDataRowSource in objDataTableSource.Rows)
                    {
                        objGuidWebId = new Guid(Convert.ToString(objDataRowSource["WebId"]));
                        objGuidListId = new Guid(Convert.ToString(objDataRowSource["ListId"]));
                        ItemId = Convert.ToInt32(objDataRowSource["ID"]);
                        using (SPWeb objSPWeb = objSPSite.OpenWeb(objGuidWebId))
                        {
                            SPListItem objSPListItem = objSPWeb.Lists[objGuidListId].GetItemById(ItemId);
                            objDataRow = dtDestination.Rows.Add();
                            objDataRow[ColumnNameFileName] = objSPListItem.File.Name;
                            objDataRow[ColumnNameFileUrl] = string.Format(@"{0}/{1}", objSPWeb.Url, objSPListItem.File.Url);
                            objDataRow[ColumnNameFileSize] = ((decimal)objSPListItem.File.Length) / lMBsize;
                            objDataRow[ColumnNameModified] = objSPListItem.File.TimeLastModified;
                            objDataRow[ColumnNameModifiedBy] = objSPListItem.File.ModifiedBy.Name;
                            //if (objSPListItem.File.ModifiedBy.LoginName.Equals(@"sharepoint\system", StringComparison.InvariantCultureIgnoreCase))
                            if (objUserProfileManager.UserExists(objSPListItem.File.ModifiedBy.LoginName) == false)
                            {
                                //  http://pdsha02:82/test/_layouts/userdisp.aspx?ID=1073741823
                                objDataRow[ColumnNameModifiedByUrl] = string.Format(@"{0}/_layouts/userdisp.aspx?ID={1}", objSPWeb.Url, objSPListItem.File.ModifiedBy.ID);
                            }
                            else
                            {
                                //  http://SharePointServer:800/Person.aspx?accountname=DomainName%5CUserLoginName
                                UserProfile p = objUserProfileManager.GetUserProfile(objSPListItem.File.ModifiedBy.LoginName);
                                objDataRow[ColumnNameModifiedByUrl] = p.PersonalUrl;

                                objDataRow[ColumnNameModifiedByUrl] = string.Format(@"{0}/Person.aspx?accountname={1}", objUserProfileManager.MySiteHostUrl, objSPListItem.File.ModifiedBy.LoginName);
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                MyLogToOperations(_logger, ex);

                throw;
            }

            return dtDestination;
        }

        public static void test1()
        {
            string strModifiedId = SPBuiltInFieldId.Modified.ToString("B");
            string strFileUrlId = SPBuiltInFieldId.URL.ToString("B");

            SPSiteDataQuery query = new SPSiteDataQuery();

            //query Document library, http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsitedataquery.lists.aspx
            query.Webs = "<Webs Scope='SiteCollection' />";
            query.Lists = "<Lists BaseType='1' />";

            //query.ViewFields = string.Format("<FieldRef Name='{0}' />", strModifiedId);
            //query.ViewFields += string.Format("<FieldRef Name='{0}' />", strFileUrlId);

            query.Query = @"<Where><Gt>" +
                "<FieldRef Name='ID' /><Value Type='Counter'>0</Value>" +
                "</Gt></Where>";
            query.Query += string.Format(@"<OrderBy Ascending='FALSE'><FieldRef Name='{0}' /></OrderBy>", strModifiedId);

            query.RowLimit = 10;

            using (SPSite objSPSite = new SPSite(@"http://localhost:82/test"))
            {
                using (SPWeb web = objSPSite.OpenWeb())
                {
                    DataTable dtSource = web.GetSiteData(query);
                    MyTraceToDeveloper(string.Format("dtSource.DefaultView.Count={0}, dtSource.DefaultView.Table.Columns.Count={1}", dtSource.DefaultView.Count, dtSource.DefaultView.Table.Columns.Count));

                    DataTable dtDest = ConvertDataTable(objSPSite, dtSource);
                    MyTraceToDeveloper(string.Format("dtDest.DefaultView.Count={0}, dtDest.DefaultView.Table.Columns.Count={1}", dtDest.DefaultView.Count, dtDest.DefaultView.Table.Columns.Count));
                }
            }
        }

        public static void test2()
        {
            string strOriginalQuery = @"<Where><IsNotNull><FieldRef Name='URL' /></IsNotNull></Where><OrderBy><FieldRef Name=""URLNoMenu"" /></OrderBy>";
            string strPermissionQuery = @"<Eq><FieldRef Name='ID' /><Value Type='Counter'>1</Value></Eq>";

            string strFinalQuery = string.Empty;
            string strOriginalWhere = string.Empty;
            string strOriginalOrder = string.Empty;
            int iPosStart = int.MinValue;
            int iPosEnd = int.MinValue;

            iPosStart = strOriginalQuery.IndexOf(@"<OrderBy>");
            iPosEnd = strOriginalQuery.IndexOf(@"</OrderBy>");
            if (iPosStart >= 0)
            {
                strOriginalOrder = strOriginalQuery.Substring(iPosStart, iPosEnd - iPosStart + 10);
            }

            if (string.IsNullOrEmpty(strPermissionQuery) == false)
            {
                if (string.IsNullOrEmpty(strOriginalQuery))
                {
                    strFinalQuery = string.Format(@"<Where>{0}</Where>", strPermissionQuery);
                }
                else if (strOriginalQuery.Contains(@"<Where>"))
                {
                    iPosStart = strOriginalQuery.IndexOf(@"<Where>");
                    iPosEnd = strOriginalQuery.IndexOf(@"</Where>");
                    strOriginalWhere = strOriginalQuery.Substring(iPosStart + 7, iPosEnd - iPosStart - 7);

                    strFinalQuery = string.Format(@"<Where><And>{0}{1}</And></Where>{2}", strOriginalWhere, strPermissionQuery, strOriginalOrder);
                }
                else
                {
                    strFinalQuery = string.Format(@"<Where>{0}</Where>{1}", strPermissionQuery, strOriginalQuery);
                }
            }
            else
            {
                strFinalQuery = strOriginalQuery;
            }

            MyTraceToDeveloper(string.Format("strOriginalQuery={0}", strOriginalQuery));
            MyTraceToDeveloper(string.Format("strPermissionQuery={0}", strPermissionQuery));
            MyTraceToDeveloper(string.Format("strOriginalWhere={0}", strOriginalWhere));
            MyTraceToDeveloper(string.Format("strOriginalOrder={0}", strOriginalOrder));
            MyTraceToDeveloper(string.Format("strFinalQuery={0}", strFinalQuery));
        }

        public static bool CheckAccessRights(string strUrl)
        {
            bool returnStatus = false;

            return returnStatus;
        }

        public static bool GetHttpStatus(string strUrl)
        {
            HttpWebRequest request = null;
            bool returnStatus = false;

            try
            {
                if (strUrl != null && strUrl != string.Empty)
                {
                    Uri uri = new Uri(strUrl);
                    request = (HttpWebRequest)HttpWebRequest.Create(uri);
                    request.Method = "GET";
                    request.KeepAlive = true;
                    request.Accept = @"*/*";
                    request.Credentials = CredentialCache.DefaultCredentials;

                    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                    {
                        returnStatus = true;
                    }
                }
            }
            //401 status codes with throw an exception in this code
            catch (System.Net.WebException)
            {
                returnStatus = false;
            }
            catch (System.Exception)
            {
                returnStatus = false;
            }

            return returnStatus;
        }

        public static string GetFinalQuery(string strOriginalQuery, string strPermissionQuery)
        {
            string strFinalQuery = string.Empty;
            string strOriginalWhere = string.Empty;
            string strOriginalOrder = string.Empty;
            int iPosStart = int.MinValue;
            int iPosEnd = int.MinValue;

            iPosStart = strOriginalQuery.IndexOf(@"<OrderBy>");
            iPosEnd = strOriginalQuery.IndexOf(@"</OrderBy>");
            if (iPosStart >= 0)
            {
                strOriginalOrder = strOriginalQuery.Substring(iPosStart, iPosEnd - iPosStart + 10);
            }

            if (string.IsNullOrEmpty(strPermissionQuery) == false)
            {
                if (string.IsNullOrEmpty(strOriginalQuery))
                {
                    strFinalQuery = string.Format(@"<Where>{0}</Where>", strPermissionQuery);
                }
                else if (strOriginalQuery.Contains(@"<Where>"))
                {
                    iPosStart = strOriginalQuery.IndexOf(@"<Where>");
                    iPosEnd = strOriginalQuery.IndexOf(@"</Where>");
                    strOriginalWhere = strOriginalQuery.Substring(iPosStart + 7, iPosEnd - iPosStart - 7);

                    strFinalQuery = string.Format(@"<Where><And>{0}{1}</And></Where>{2}", strOriginalWhere, strPermissionQuery, strOriginalOrder);
                }
                else
                {
                    strFinalQuery = string.Format(@"<Where>{0}</Where>{1}", strPermissionQuery, strOriginalQuery);
                }
            }
            else
            {
                strFinalQuery = strOriginalQuery;
            }

            return strFinalQuery;
        }

        public static List<int> GetListItemIDs(SPView objSPView)
        {
            Guid guidFieldNameUrl = Guid.Empty;
            SPFieldUrlValue valueUrl = null;
            string strURL = string.Empty;
            List<int> listItemID = new List<int>();

            SPList objSPList = objSPView.ParentList;
            SPListItemCollection objSPListItemCollection = objSPList.GetItems(objSPView);
            foreach (SPField objSPField in objSPListItemCollection.Fields)
            {
                if (objSPField.Type == SPFieldType.URL || objSPField.Type == SPFieldType.Computed)
                {
                    if (objSPList.Fields[objSPField.Title].FieldValueType != null && objSPList.Fields[objSPField.Title].FieldValueType.Name.Equals("SPFieldUrlValue", StringComparison.InvariantCultureIgnoreCase))
                    {
                        guidFieldNameUrl = objSPField.Id;
                        break;
                    }
                }
            }

            if (guidFieldNameUrl != Guid.Empty)
            {
                foreach (SPListItem item in objSPListItemCollection)
                {
                    valueUrl = new SPFieldUrlValue(item[guidFieldNameUrl].ToString());
                    strURL = valueUrl.Url;
                    if (GetHttpStatus(strURL) == false)
                    {
                        MyTraceToDeveloper(string.Format("Cannot access url: {0}", strURL));
                        listItemID.Add(item.ID);
                    }
                    else
                    {
                        MyTraceToDeveloper(string.Format("Can access url: {0}", strURL));
                    }
                }
            }

            return listItemID;
        }

        public static string GetNewQueryBasedOnAccessPermissions(SPView objSPView)
        {
            string strPermissionQuery = string.Empty;
            string strCurrentWhere = string.Empty;
            List<int> listItemIDs = null;

            listItemIDs = GetListItemIDs(objSPView);
            if (listItemIDs.Count > 0)
            {
                foreach (int iItemID in listItemIDs)
                {
                    strCurrentWhere = string.Format(@"<Neq><FieldRef Name='ID' /><Value Type='Counter'>{0}</Value></Neq>", iItemID);
                    if (string.IsNullOrEmpty(strPermissionQuery))
                    {
                        strPermissionQuery = strCurrentWhere;
                    }
                    else
                    {
                        strPermissionQuery = string.Format(@"<And>{0}{1}</And>", strPermissionQuery, strCurrentWhere);
                    }
                }
            }

            return strPermissionQuery;
        }

        public static void test3()
        {
            string strPermissionQuery = string.Empty;
            using (SPSite objSPSite = new SPSite(@"http://pdsha02:81/test"))
            {
                using (SPWeb objSPWeb = objSPSite.OpenWeb())
                {
                    SPView objSPView = objSPWeb.GetViewFromUrl(@"Lists/Links/AllItems.aspx");
                    SPList objSPList = objSPView.ParentList;

                    string strOriginalQuery = objSPView.Query;
                    strPermissionQuery = GetNewQueryBasedOnAccessPermissions(objSPView);
                    MyTraceToDeveloper(string.Format("strPermissionQuery={0}", strPermissionQuery));
                    string strFinalQuery = GetFinalQuery(strOriginalQuery, strPermissionQuery);
                    MyTraceToDeveloper(string.Format("strFinalQuery={0}", strFinalQuery));
                    objSPView.Query = strFinalQuery;
                    SPListItemCollection objSPListItemCollection = objSPList.GetItems(objSPView);
                    MyTraceToDeveloper(string.Format("objSPListItemCollection.Count={0}", objSPListItemCollection.Count));
                }
            }

        }

        static void Main(string[] args)
        {
            MyTraceToDeveloper("Start.");

            //test1();
            //test2();
            test3();

            MyTraceToDeveloper("Completed.  Press enter key to exit.");
            Console.ReadLine();
        }
    }
}
